//
//  GMHTTPSessionManager.m
//  CocoaPodsTest
//
//  Created by suixuexiang on 14/1/15.
//  Copyright (c) 2015 ___MASTER___. All rights reserved.
//

#import "GMHTTPSessionManager.h"
#import <Foundation/NSURLRequest.h>
#import "CocoaSecurity.h"
#import "UIDevice+IdentifierAddition.h"
#import "NSString+DeviceTypeHelper.h"

//idfa
#import <AdSupport/ASIdentifierManager.h>

static NSString *KEY_DEVICE_KEY = @"DeviceIdentifier";
static NSString *KEY_DEVICE = @"Device";
static NSString *KEY_SIGNATURE = @"Signature";
static NSString *KEY_TIMESTAMP = @"timeStamp";
static NSString *KEY_VERSION   = @"app_version";
static NSString *KEY_SYSTEM = @"System";
static NSString *STR_PRIVATEKEY = @"golf";

static NSURLRequestCachePolicy DEFAULT_CACHE_POLICY = NSURLRequestUseProtocolCachePolicy;
//idfa
static NSString *KEY_MASTERADID = @"idfa";

@interface GMHTTPSessionManager()

@property (nonatomic, strong) AFHTTPRequestSerializer <AFURLRequestSerialization> * returnCacheDataElseLoadRequestSerializer;

@end

@implementation GMHTTPSessionManager

+ (instancetype)shared {
    static GMHTTPSessionManager *shared = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        // Network activity indicator manager setup
        shared = [self new];
    }
    );
    
    return shared;
}

- (instancetype)init
{
    NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
    NSURLCache *cache = [[NSURLCache alloc] initWithMemoryCapacity:10 * 1024 * 1024
                                                      diskCapacity:50 * 1024 * 1024
                                                          diskPath:nil];
    [sessionConfiguration setURLCache:cache];
    sessionConfiguration.requestCachePolicy = DEFAULT_CACHE_POLICY;

    sessionConfiguration.HTTPAdditionalHeaders = [self globalAdditionalHeaders];
    
    self = [super initWithBaseURL:nil sessionConfiguration:sessionConfiguration];
    if (!self) {
        return nil;
    }

    return self;
}

- (NSDictionary *)globalAdditionalHeaders
{
    NSString *systemString = [NSString stringWithFormat:@"%@%@",[[UIDevice currentDevice] systemName], [[UIDevice currentDevice] systemVersion]];
    
    NSString *deviceString = [NSString deviceType];
    NSString *deviceIdentifier = [[UIDevice currentDevice] uniqueDeviceIdentifier];

    NSDictionary *globalAdditionalHeaders = @{KEY_DEVICE:deviceString,KEY_DEVICE_KEY:deviceIdentifier,
                                              KEY_SYSTEM:systemString};
    
    return globalAdditionalHeaders;
}

- (void)addAddtionalheaders:(AFHTTPRequestSerializer <AFURLRequestSerialization> *)requestSerializer
{
    NSParameterAssert(requestSerializer);
    
    NSString *dynamicTimeStamp = [NSString stringWithFormat:@"%.0f",[[NSDate date] timeIntervalSince1970]];
                                  
    NSString *encryptionBySHA256 = [[CocoaSecurity sha256:
                                     [NSString stringWithFormat:@"%@%@", dynamicTimeStamp,STR_PRIVATEKEY]
                                     ] hexLower];
    NSString *encryptionByMD5 = [[CocoaSecurity md5:
                                  [NSString stringWithFormat:@"%@%@", encryptionBySHA256, dynamicTimeStamp]] hexLower];
    
    NSString *gmVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];
    NSString *gmBundle  = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];
    NSString *versionHeader = [NSString stringWithFormat:@"%@_%@",gmVersion,gmBundle];
    
    //idfa
    NSString *master_idfa = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];//广告标示符
    
    if (master_idfa && master_idfa.length>0) {
        
        [requestSerializer setValue:master_idfa forHTTPHeaderField:KEY_MASTERADID];
        
    }
    [requestSerializer setValue:dynamicTimeStamp forHTTPHeaderField:KEY_TIMESTAMP];
    [requestSerializer setValue:encryptionByMD5 forHTTPHeaderField:KEY_SIGNATURE];
    [requestSerializer setValue:versionHeader forHTTPHeaderField:KEY_VERSION];
}

#pragma newly added get function

/**
 * GET request with cache policy
 * NSURLRequestReloadIgnoringLocalCacheData:    don't use cache in request
 * NSURLRequestReturnCacheDataElseLoad:         do firt loading operation, if no cache, load the network
 * NSURLRequestReturnCacheDataDontLoad:         only use cache, don't load network
 * else:                                        please use GET fucntion wich has no parameters cache policy
 * note: 304 and etag mechanims has been implemented in the default polocy
 *
 * Fix me:
 * Fix me:
 * the function is not thread safe, Please ensure the cache policy would not be often changed.
 * the function would cause very serious header error, if you cocurrently invoking
 */
- (NSURLSessionDataTask *)GET:(NSString *)URLString
                          parameters:(id)parameters
                          success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
                          failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
                  cachePolicy:(NSURLRequestCachePolicy)cachePolicy
{
    NSURLSessionDataTask *task = nil;
    @synchronized(self.requestSerializer){
        self.requestSerializer.cachePolicy = cachePolicy;
        [self addAddtionalheaders:self.requestSerializer];
        task = [super GET:URLString parameters:parameters success:success failure:failure];
    }
    
    return task;
}

#pragma overload the http functions

- (NSURLSessionDataTask *)HEAD:(NSString *)URLString
                    parameters:(id)parameters
                       success:(void (^)(NSURLSessionDataTask *task))success
                       failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
{
    NSURLSessionDataTask *task = nil;
    @synchronized(self.requestSerializer){
        [self addAddtionalheaders:self.requestSerializer];
        task = [super HEAD:URLString parameters:parameters success:success failure:failure];
    }
    
    return task;
}

- (NSURLSessionDataTask *)POST:(NSString *)URLString
                     parameters:(id)parameters
                       success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
                       failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
{
    NSURLSessionDataTask *task = nil;
    @synchronized(self.requestSerializer){
        [self addAddtionalheaders:self.requestSerializer];
        task = [super POST:URLString parameters:parameters success:success failure:failure];
    }
    
    return task;
}

- (NSURLSessionDataTask *)POST:(NSString *)URLString
                    parameters:(id)parameters
     constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))block
                       success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
                       failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
{
    NSURLSessionDataTask *task = nil;
    @synchronized(self.requestSerializer){
        [self addAddtionalheaders:self.requestSerializer];
        task = [super POST:URLString parameters:parameters constructingBodyWithBlock:block success:success failure:failure];
        //DLog(@"task :%@",task);
    }
    
    return task;
}

- (NSURLSessionDataTask *)PUT:(NSString *)URLString
                   parameters:(id)parameters
                      success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
                      failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
{
    NSURLSessionDataTask *task = nil;
    @synchronized(self.requestSerializer){
        [self addAddtionalheaders:self.requestSerializer];
        task = [super PUT:URLString parameters:parameters success:success failure:failure];
    }
    
    return task;
}

- (NSURLSessionDataTask *)PUT:(NSString *)URLString
                   parameters:(id)parameters
    constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))block
                      success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
                      failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
{
    NSMutableURLRequest *request = [self.requestSerializer multipartFormRequestWithMethod:@"PUT" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters constructingBodyWithBlock:block error:nil];
    
    __block NSURLSessionDataTask *task = [self uploadTaskWithStreamedRequest:request progress:nil completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) {
        if (error) {
            if (failure) {
                failure(task, error);
            }
        } else {
            if (success) {
                success(task, responseObject);
            }
        }
    }];
    
    [task resume];
    
    return task;
}

- (NSURLSessionDataTask *)PATCH:(NSString *)URLString
                     parameters:(id)parameters
                        success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
                        failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
{
    NSURLSessionDataTask *task = nil;
    @synchronized(self.requestSerializer){
        [self addAddtionalheaders:self.requestSerializer];
        task = [super PATCH:URLString parameters:parameters success:success failure:failure];
    }
    
    return task;
}

- (NSURLSessionDataTask *)DELETE:(NSString *)URLString
                      parameters:(id)parameters
                         success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
                         failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
{
    NSURLSessionDataTask *task = nil;
    @synchronized(self.requestSerializer){
        [self addAddtionalheaders:self.requestSerializer];
        task = [super DELETE:URLString parameters:parameters success:success failure:failure];
    }
    
    return task;
}

@end
